From 8e4f8a45a9b8cda3bc3d12fb50d805897b1902e2 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 13 Oct 2020 21:23:22 -0400 Subject: [PATCH] atspi: Implement Component Implement the non-questionable parts of the Component interface for accessibles which are widgets. This does not include: - global coordinates - setters - scrolling - alpha, layers, zorder, and the like --- gtk/a11y/gtkatspicomponent.c | 244 ++++++++++++++++++++++++++++ gtk/a11y/gtkatspicomponentprivate.h | 30 ++++ gtk/a11y/gtkatspicontext.c | 17 ++ gtk/a11y/gtkatspiprivate.h | 6 + gtk/a11y/meson.build | 1 + 5 files changed, 298 insertions(+) create mode 100644 gtk/a11y/gtkatspicomponent.c create mode 100644 gtk/a11y/gtkatspicomponentprivate.h diff --git a/gtk/a11y/gtkatspicomponent.c b/gtk/a11y/gtkatspicomponent.c new file mode 100644 index 0000000000..2ab1ffc81c --- /dev/null +++ b/gtk/a11y/gtkatspicomponent.c @@ -0,0 +1,244 @@ +/* gtkatspicomponent.c: AT-SPI Component implementation + * + * Copyright 2020 Red Hat, Inc. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "config.h" + +#include "gtkatspicomponentprivate.h" + +#include "gtkatspicontextprivate.h" +#include "gtkatspiprivate.h" +#include "gtkatspiutilsprivate.h" +#include "gtkaccessibleprivate.h" +#include "gtkwidget.h" + +#include "a11y/atspi/atspi-component.h" + +#include "gtkdebug.h" + +#include + +static void +translate_coordinates_to_widget (GtkWidget *widget, + AtspiCoordType coordtype, + int xi, + int yi, + int *xo, + int *yo) +{ + double x = xi; + double y = yi; + + switch (coordtype) + { + case ATSPI_COORD_TYPE_SCREEN: + g_warning ("Screen coordinates not supported, reported positions will be wrong"); + G_GNUC_FALLTHROUGH; + + case ATSPI_COORD_TYPE_WINDOW: + gtk_widget_translate_coordinates (GTK_WIDGET (gtk_widget_get_root (widget)), + widget, + x, y, + &x, &y); + break; + + case ATSPI_COORD_TYPE_PARENT: + gtk_widget_translate_coordinates (gtk_widget_get_parent (widget), + widget, + x, y, + &x, &y); + break; + + default: + g_assert_not_reached (); + } + + *xo = (int)x; + *yo = (int)y; +} + +static void +translate_coordinates_from_widget (GtkWidget *widget, + AtspiCoordType coordtype, + int xi, + int yi, + int *xo, + int *yo) +{ + double x = xi; + double y = yi; + + switch (coordtype) + { + case ATSPI_COORD_TYPE_SCREEN: + g_warning ("Screen coordinates not supported, reported positions will be wrong"); + G_GNUC_FALLTHROUGH; + + case ATSPI_COORD_TYPE_WINDOW: + gtk_widget_translate_coordinates (widget, + GTK_WIDGET (gtk_widget_get_root (widget)), + x, y, + &x, &y); + break; + + case ATSPI_COORD_TYPE_PARENT: + gtk_widget_translate_coordinates (widget, + gtk_widget_get_parent (widget), + x, y, + &x, &y); + break; + + default: + g_assert_not_reached (); + } + + *xo = (int)x; + *yo = (int)y; +} + +static void +component_handle_method (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GtkATContext *self = user_data; + GtkAccessible *accessible = gtk_at_context_get_accessible (self); + GtkWidget *widget = GTK_WIDGET (accessible); + + if (g_strcmp0 (method_name, "Contains") == 0) + { + int x, y; + AtspiCoordType coordtype; + gboolean ret; + + g_variant_get (parameters, "(iiu)", &x, &y, &coordtype); + + translate_coordinates_to_widget (widget, coordtype, x, y, &x, &y); + + ret = gtk_widget_contains (widget, x, y); + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret)); + } + else if (g_strcmp0 (method_name, "GetAccessibleAtPoint") == 0) + { + int x, y; + AtspiCoordType coordtype; + GtkWidget *child; + + g_variant_get (parameters, "(iiu)", &x, &y, &coordtype); + + translate_coordinates_to_widget (widget, coordtype, x, y, &x, &y); + + child = gtk_widget_pick (widget, x, y, GTK_PICK_DEFAULT); + if (!child) + { + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(@(so))", gtk_at_spi_null_ref ())); + } + else + { + GtkAtSpiContext *ctx = GTK_AT_SPI_CONTEXT (gtk_accessible_get_at_context (GTK_ACCESSIBLE (child))); + + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(@(so))", gtk_at_spi_context_to_ref (ctx))); + } + } + else if (g_strcmp0 (method_name, "GetExtents") == 0) + { + AtspiCoordType coordtype; + int x, y; + int width = gtk_widget_get_width (widget); + int height = gtk_widget_get_height (widget); + + g_variant_get (parameters, "(u)", &coordtype); + + translate_coordinates_from_widget (widget, coordtype, 0, 0, &x, &y); + + g_dbus_method_invocation_return_value (invocation, g_variant_new ("((iiii))", x, y, width, height)); + } + else if (g_strcmp0 (method_name, "GetPosition") == 0) + { + AtspiCoordType coordtype; + int x, y; + + g_variant_get (parameters, "(u)", &coordtype); + + translate_coordinates_from_widget (widget, coordtype, 0, 0, &x, &y); + + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(ii)", x, y)); + } + else if (g_strcmp0 (method_name, "GetSize") == 0) + { + int width = gtk_widget_get_width (widget); + int height = gtk_widget_get_height (widget); + + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(ii)", width, height)); + } + else if (g_strcmp0 (method_name, "GetLayer") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } + else if (g_strcmp0 (method_name, "GetMDIZOrder") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } + else if (g_strcmp0 (method_name, "GrabFocus") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } + else if (g_strcmp0 (method_name, "GetAlpha") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } + else if (g_strcmp0 (method_name, "SetExtents") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } + else if (g_strcmp0 (method_name, "SetPosition") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } + else if (g_strcmp0 (method_name, "SetSize") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } + else if (g_strcmp0 (method_name, "ScrollTo") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } + else if (g_strcmp0 (method_name, "ScrollToPoint") == 0) + { + g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, ""); + } +} + +static const GDBusInterfaceVTable component_vtable = { + component_handle_method, +}; + +const GDBusInterfaceVTable * +gtk_atspi_get_component_vtable (GtkAccessible *accessible) +{ + if (GTK_IS_WIDGET (accessible)) + return &component_vtable; + + return NULL; +} diff --git a/gtk/a11y/gtkatspicomponentprivate.h b/gtk/a11y/gtkatspicomponentprivate.h new file mode 100644 index 0000000000..157a6e9eca --- /dev/null +++ b/gtk/a11y/gtkatspicomponentprivate.h @@ -0,0 +1,30 @@ +/* gtkatspicomponentprivate.h: AT-SPI Component implementation + * + * Copyright 2020 Red Hat, Inc. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#pragma once + +#include +#include "gtkaccessible.h" + +G_BEGIN_DECLS + +const GDBusInterfaceVTable *gtk_atspi_get_component_vtable (GtkAccessible *accessible); + +G_END_DECLS diff --git a/gtk/a11y/gtkatspicontext.c b/gtk/a11y/gtkatspicontext.c index bed789f048..53589b9466 100644 --- a/gtk/a11y/gtkatspicontext.c +++ b/gtk/a11y/gtkatspicontext.c @@ -33,6 +33,7 @@ #include "gtkatspitextprivate.h" #include "gtkatspiutilsprivate.h" #include "gtkatspivalueprivate.h" +#include "gtkatspicomponentprivate.h" #include "a11y/atspi/atspi-accessible.h" #include "a11y/atspi/atspi-action.h" @@ -40,6 +41,7 @@ #include "a11y/atspi/atspi-text.h" #include "a11y/atspi/atspi-value.h" #include "a11y/atspi/atspi-selection.h" +#include "a11y/atspi/atspi-component.h" #include "gtkdebug.h" #include "gtkeditable.h" @@ -989,6 +991,21 @@ gtk_at_spi_context_register_object (GtkAtSpiContext *self) NULL); self->n_registered_objects++; + vtable = gtk_atspi_get_component_vtable (accessible); + if (vtable) + { + g_variant_builder_add (&interfaces, "s", atspi_component_interface.name); + self->registration_ids[self->n_registered_objects] = + g_dbus_connection_register_object (self->connection, + self->context_path, + (GDBusInterfaceInfo *) &atspi_component_interface, + vtable, + self, + NULL, + NULL); + self->n_registered_objects++; + } + vtable = gtk_atspi_get_text_vtable (accessible); if (vtable) { diff --git a/gtk/a11y/gtkatspiprivate.h b/gtk/a11y/gtkatspiprivate.h index 6b35e0df6c..9d3d316354 100644 --- a/gtk/a11y/gtkatspiprivate.h +++ b/gtk/a11y/gtkatspiprivate.h @@ -246,4 +246,10 @@ typedef enum { ATSPI_TEXT_GRANULARITY_PARAGRAPH } AtspiTextGranularity; +typedef enum { + ATSPI_COORD_TYPE_SCREEN, + ATSPI_COORD_TYPE_WINDOW, + ATSPI_COORD_TYPE_PARENT, +} AtspiCoordType; + G_END_DECLS diff --git a/gtk/a11y/meson.build b/gtk/a11y/meson.build index 5cb0cc88f2..7fff19549a 100644 --- a/gtk/a11y/meson.build +++ b/gtk/a11y/meson.build @@ -11,6 +11,7 @@ if gtk_a11y_backends.contains('atspi') gtk_a11y_src += files([ 'gtkatspiaction.c', 'gtkatspicache.c', + 'gtkatspicomponent.c', 'gtkatspicontext.c', 'gtkatspieditabletext.c', 'gtkatspipango.c', -- 2.30.2